package com.xuecheng.content.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.base.exception.CommonError;
import com.xuecheng.base.exception.XueChengPlusException;
import com.xuecheng.content.config.MultipartSupportConfig;
import com.xuecheng.content.feignclient.MediaServiceClient;
import com.xuecheng.content.mapper.CoursePublishMapper;
import com.xuecheng.content.model.dto.CourseBaseInfoDto;
import com.xuecheng.content.model.dto.CoursePreviewDto;
import com.xuecheng.content.model.dto.TeachplanDto;
import com.xuecheng.content.model.po.*;
import com.xuecheng.content.service.*;
import com.xuecheng.messagesdk.model.po.MqMessage;
import com.xuecheng.messagesdk.service.MqMessageService;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @description TODO
 * @author Mr.M
 * @date 2022/9/16 15:37
 * @version 1.0
 */
@Slf4j
@Service
public class CoursePublishServiceImpl extends ServiceImpl<CoursePublishMapper, CoursePublish> implements CoursePublishService {

 @Autowired
 CourseBaseInfoService courseBaseInfoService;

 @Autowired
 TeachPlanService teachplanService;

 @Autowired
 CourseMarketService courseMarketService;

 @Autowired
 CourseTeacherService courseTeacherService ;

 @Autowired
 CoursePublishPreService coursePublishPreService ;

 @Autowired
 CourseBaseService courseBaseService ;

 @Autowired
 CoursePublishService coursePublishService ;

 @Autowired
 MqMessageService mqMessageService ;

 @Autowired
 MediaServiceClient mediaServiceClient ;


 @Autowired
 RedisTemplate redisTemplate ;

 @Autowired
 RedissonClient redissonClient ;

 @Override
 public CoursePreviewDto getCoursePreviewInfo(Long courseId) {

  //课程基本信息、营销信息
  CourseBaseInfoDto courseBaseInfo = courseBaseInfoService.getCourseBaseInfo(courseId);

  //课程计划信息
  List<TeachplanDto> teachplanTree= teachplanService.findTeachPlanTree(courseId);

  List<CourseTeacher> courseTeacher = courseTeacherService.getCourseTeacher(courseId);

  CoursePreviewDto coursePreviewDto = new CoursePreviewDto();
  coursePreviewDto.setCourseBase(courseBaseInfo);
  coursePreviewDto.setTeachplans(teachplanTree);
  coursePreviewDto.setTeachers(courseTeacher);
  return coursePreviewDto;
 }

 @Override
 @Transactional
 public void commitAudit(Long companyId, Long courseId) {
  CourseBaseInfoDto courseBaseInfo = courseBaseInfoService.getCourseBaseInfo(courseId);
  if(StringUtils.isEmpty(courseBaseInfo)){
   XueChengPlusException.cast("课程找不到");
  }
//  审核状态
  String auditStatus = courseBaseInfo.getAuditStatus();
  if(auditStatus.equals("202003")){
   XueChengPlusException.cast("课程已提交请等待审核");
  }

  if(StringUtils.isEmpty(courseBaseInfo.getPic())){
   XueChengPlusException.cast("请上传图片");
  }

//  查询课程计划
  List<TeachplanDto> teachPlanTree = teachplanService.findTeachPlanTree(courseId);
  if(StringUtils.isEmpty(teachPlanTree)){
   XueChengPlusException.cast("请编写课程计划");
  }
  CoursePublishPre coursePublishPre = new CoursePublishPre();
  coursePublishPre.setCompanyId(companyId);

//  查询到课程基本信息、详细信息、计划信息记录到课程发布表
  BeanUtils.copyProperties(courseBaseInfo,coursePublishPre);
//  营销信息
  CourseMarket courseMarket = courseMarketService.selectById(courseId);
//  转json
  String courseMarketJson = JSON.toJSONString(courseMarket);
  coursePublishPre.setMarket(courseMarketJson);

  //计划信息
  String teachPlanTreeJson = JSON.toJSONString(teachPlanTree);
  coursePublishPre.setTeachplan(teachPlanTreeJson);

  List<CourseTeacher> courseTeacher = courseTeacherService.getCourseTeacher(courseId);
  String courseTeacherJson = JSON.toJSONString(courseTeacher);
  coursePublishPre.setTeachers(courseTeacherJson);


  coursePublishPre.setStatus("202003");
  coursePublishPre.setCreateDate(LocalDateTime.now());

//  查询预发布表，如果有记录更新，没有记录插入/**/
  CoursePublishPre coursePublishPreObj =coursePublishPreService.getById(courseId);
   if(StringUtils.isEmpty(coursePublishPreObj)){
 //   插入
    coursePublishPreService.save(coursePublishPre);
   }else{
//    更新
    coursePublishPreService.updateById(coursePublishPre) ;
   }

//   更新课程基本信息表的审核状态为已提交
  CourseBase courseBase = courseBaseService.getById(courseId);
  courseBase.setAuditStatus("202003");

  courseBaseService.updateById(courseBase) ;
 }

 @Transactional
 @Override
 public void publish(Long companyId, Long courseId) {

//  查询预发布表
  CoursePublishPre coursePublishPre = coursePublishPreService.getById(courseId);
  if(StringUtils.isEmpty(coursePublishPre)){
   XueChengPlusException.cast("课程没有审核记录，无法发布");
  }
  String status = coursePublishPre.getStatus();
//  课程如果没有审核通过不允许发布
if(!status.equals("202004")){
 XueChengPlusException.cast("课程没有审核通过不允许发布");
}
//向课程发布表写入数据
  CoursePublish coursePublish = new CoursePublish();
  BeanUtils.copyProperties(coursePublishPre,coursePublish);

  CoursePublish coursePublishObj = coursePublishService.getById(courseId);
  if(coursePublishObj == null){
   coursePublishService.save(coursePublish);
  }else{
   coursePublishService.updateById(coursePublishObj) ;
  }

//  向消息表写入数据
//  mqMessageService.addMessage("course_publish",String.valueOf(courseId),null,null) ;
  saveCoursePublishMessage(courseId);


//  将发布表数据删除
  coursePublishPreService.removeById(courseId);


 }

 @Override
 public File generateCourseHtml(Long courseId) {

  //配置freemarker
  Configuration configuration = new Configuration(Configuration.getVersion());
  File htmlFile = null ;
  try{


  //加载模板
  //选指定模板路径,classpath下templates下
  //得到classpath路径
  String classpath = this.getClass().getResource("/").getPath();
  configuration.setDirectoryForTemplateLoading(new File(classpath + "/templates/"));
  //设置字符编码
  configuration.setDefaultEncoding("utf-8");

  //指定模板文件名称
  Template template = configuration.getTemplate("course_template.ftl");

  //准备数据
  CoursePreviewDto coursePreviewInfo = this.getCoursePreviewInfo(courseId);

  Map<String, Object> map = new HashMap<>();
  map.put("model", coursePreviewInfo);

        //静态化
        //参数1：模板，参数2：数据模型
        String html = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
        System.out.println(html);
        //将静态化内容输出到文件中
        InputStream inputStream = IOUtils.toInputStream(html,"utf-8");
        htmlFile = File.createTempFile("coursepublish",".html");
        //输出流
        FileOutputStream outputStream = new FileOutputStream(htmlFile);
        IOUtils.copy(inputStream, outputStream);

  }catch (Exception e){
   log.error("页面静态话异常，课程id:{}",courseId,e);
   e.printStackTrace();
  }
  return htmlFile ;
 }

 @Override
 public void uploadCourseHtml(Long courseId, File file) {
  try {
   MultipartFile multipartFile = MultipartSupportConfig.getMultipartFile(file);
   String uploadFile = mediaServiceClient.uploadFile(multipartFile, "course/" + courseId + ".html");
   if (StringUtils.isEmpty(uploadFile)) {
    log.error("远程调用走降级逻辑得到的上传结果为null,课程id:{}", courseId);
    XueChengPlusException.cast("上传静态文件存在异常");
   }
  }catch (Exception e){
   XueChengPlusException.cast("上传静态文件存在异常");
  }
 }

 /**
  * 根据课程id查询课程发布信息
  * @param courseId
  * @return
  */
 @Override
 public CoursePublish getCoursePublish(Long courseId) {
  CoursePublish coursePublish = coursePublishService.getById(courseId);
  return coursePublish;
 }

 @Override
 public CoursePublish getCoursePublishCache(Long courseId) {

   //查询缓存
   Object jsonObj = redisTemplate.opsForValue().get("course:" + courseId);
//  if("null".equals(jsonString)){
//   return null ;
//  }
  CoursePublish coursePublish = null ;
   if (jsonObj != null) {
    System.out.println("=================从缓存查=================");
    String jsonString = jsonObj.toString();
    if ("null".equals(jsonString)) {
     return null;
    }
     coursePublish = JSON.parseObject(jsonString, CoursePublish.class);

    return coursePublish;
   } else {
    RLock lock = redissonClient.getLock("coursequerylock:" + courseId);
    lock.lock();
    try{
     jsonObj = redisTemplate.opsForValue().get("course:" + courseId);
     if(!StringUtils.isEmpty(jsonObj)){
      String jsonString = jsonObj.toString();
      if ("null".equals(jsonString)) {
       return null;
      }
      coursePublish = JSON.parseObject(jsonString, CoursePublish.class);
      return coursePublish ;
     }
     System.out.println("从数据库查询...");


//     try {
//      Thread.sleep(60000);
//     } catch (InterruptedException e) {
//      e.printStackTrace();
//     }



     //从数据库查询
     coursePublish = getCoursePublish(courseId);
//   if(coursePublish!=null){
     redisTemplate.opsForValue().set("course:" + courseId, JSON.toJSONString(coursePublish), 300 + new Random().nextInt(100), TimeUnit.SECONDS);
//   }
     return coursePublish;

    }finally {

     lock.unlock();


   }


  }
 }
// @Override
// public CoursePublish getCoursePublishCache(Long courseId) {
//
//   //查询缓存
//   Object jsonObj = redisTemplate.opsForValue().get("course:" + courseId);
////  if("null".equals(jsonString)){
////   return null ;
////  }
//  CoursePublish coursePublish = null ;
//   if (jsonObj != null) {
//    System.out.println("=================从缓存查=================");
//    String jsonString = jsonObj.toString();
//    if ("null".equals(jsonString)) {
//     return null;
//    }
//     coursePublish = JSON.parseObject(jsonString, CoursePublish.class);
//
//    return coursePublish;
//   } else {
//    synchronized (this) {
//     jsonObj = redisTemplate.opsForValue().get("course:" + courseId);
//     if(!StringUtils.isEmpty(jsonObj)){
//        String jsonString = jsonObj.toString();
//        if ("null".equals(jsonString)) {
//         return null;
//        }
//       coursePublish = JSON.parseObject(jsonString, CoursePublish.class);
//        return coursePublish ;
//     }
//
//    System.out.println("从数据库查询...");
//    //从数据库查询
//     coursePublish = getCoursePublish(courseId);
////   if(coursePublish!=null){
//    redisTemplate.opsForValue().set("course:" + courseId, JSON.toJSONString(coursePublish), 300 + new Random().nextInt(100), TimeUnit.SECONDS);
////   }
//    return coursePublish;
//   }
//  }
// }

 /**
  * @description 保存消息表记录
  * @param courseId  课程id
  * @return void
  * @author Mr.M
  * @date 2022/9/20 16:32
  */
 private void saveCoursePublishMessage(Long courseId) {
  MqMessage mqMessage = mqMessageService.addMessage("course_publish", String.valueOf(courseId), null, null);
  if (mqMessage == null) {
   XueChengPlusException.cast(CommonError.UNKOWN_ERROR);
  }
 }

}